package com.itheima.book.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.book.mapper.BookMapper;
import com.itheima.book.mapper.CategoryMapper;
import com.itheima.book.service.BookAdminService;
import com.itheima.common.constants.KafkaConstants;
import com.itheima.model.book.dtos.BookAdminDto;
import com.itheima.model.book.dtos.BookEventDto;
import com.itheima.model.book.dtos.BookSaveDto;
import com.itheima.model.book.pojos.Book;
import com.itheima.model.book.pojos.Category;
import com.itheima.model.book.vos.BookAdminVo;
import com.itheima.model.common.dtos.PageResponseResult;
import com.itheima.model.common.dtos.ResponseResult;
import com.itheima.model.common.enums.AppHttpCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 图书管理后台服务实现
 * 
 * @author itheima
 */
@Slf4j
@Service
public class BookAdminServiceImpl implements BookAdminService {

    @Autowired
    private BookMapper bookMapper;
    
    @Autowired
    private CategoryMapper categoryMapper;
    
    @Autowired(required = false)
    private KafkaTemplate<String, String> kafkaTemplate;

    @Override
    public ResponseResult listBooks(BookAdminDto dto) {
        try {
            // 校验参数
            dto.checkParam();

            // 构建查询条件
            LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();

            // 标题模糊查询
            if (StringUtils.hasText(dto.getTitle())) {
                queryWrapper.like(Book::getTitle, dto.getTitle());
            }

            // 作者模糊查询
            if (StringUtils.hasText(dto.getAuthor())) {
                queryWrapper.like(Book::getAuthor, dto.getAuthor());
            }

            // 分类精确查询
            if (dto.getCategoryId() != null) {
                queryWrapper.eq(Book::getCategoryId, dto.getCategoryId());
            }

            // 出版社模糊查询
            if (StringUtils.hasText(dto.getPublisher())) {
                queryWrapper.like(Book::getPublisher, dto.getPublisher());
            }

            // 按创建时间倒序
            queryWrapper.orderByDesc(Book::getCreateTime);

            // 分页查询
            IPage<Book> pageObj = new Page<>(dto.getPage(), dto.getSize());
            IPage<Book> result = bookMapper.selectPage(pageObj, queryWrapper);

            // 转换为VO并填充分类名称
            List<BookAdminVo> bookAdminVoList = convertToAdminVo(result.getRecords());

            // 构建响应结果
            PageResponseResult pageResponse = new PageResponseResult(
                dto.getPage(), 
                dto.getSize(), 
                (int) result.getTotal()
            );
            pageResponse.setData(bookAdminVoList);

            return pageResponse;
        } catch (Exception e) {
            log.error("查询图书列表失败", e);
            return ResponseResult.errorResult(500, "查询图书列表失败：" + e.getMessage());
        }
    }

    @Override
    public ResponseResult getBookById(Integer id) {
        try {
            if (id == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "图书ID不能为空");
            }

            Book book = bookMapper.selectById(id);
            if (book == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "图书不存在");
            }

            return ResponseResult.okResult(book);
        } catch (Exception e) {
            log.error("获取图书详情失败, id={}", id, e);
            return ResponseResult.errorResult(500, "获取图书详情失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ResponseResult addBook(BookSaveDto dto) {
        try {
            Book book = new Book();
            BeanUtils.copyProperties(dto, book);
            book.setCreateTime(new Date());
            book.setUpdateTime(new Date());

            int count = bookMapper.insert(book);
            if (count > 0) {
                // 发送Kafka消息：新增图书
                sendBookEvent(BookEventDto.createAddEvent(book.getId(), book.getTitle()));
                return ResponseResult.okResult(book);
            } else {
                return ResponseResult.errorResult(500, "新增图书失败");
            }
        } catch (Exception e) {
            log.error("新增图书失败", e);
            return ResponseResult.errorResult(500, "新增图书失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ResponseResult updateBook(BookSaveDto dto) {
        try {
            if (dto.getId() == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "图书ID不能为空");
            }

            // 检查图书是否存在
            Book existBook = bookMapper.selectById(dto.getId());
            if (existBook == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "图书不存在");
            }

            // 更新图书信息
            Book book = new Book();
            BeanUtils.copyProperties(dto, book);
            book.setUpdateTime(new Date());

            int count = bookMapper.updateById(book);
            if (count > 0) {
                // 发送Kafka消息：更新图书
                sendBookEvent(BookEventDto.createUpdateEvent(book.getId(), book.getTitle()));
                return ResponseResult.okResult(book);
            } else {
                return ResponseResult.errorResult(500, "更新图书失败");
            }
        } catch (Exception e) {
            log.error("更新图书失败, id={}", dto.getId(), e);
            return ResponseResult.errorResult(500, "更新图书失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ResponseResult deleteBook(Integer id) {
        try {
            if (id == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "图书ID不能为空");
            }

            // 检查图书是否存在
            Book book = bookMapper.selectById(id);
            if (book == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "图书不存在");
            }

            // 删除图书
            int count = bookMapper.deleteById(id);
            if (count > 0) {
                // 发送Kafka消息：删除图书，通知search-service删除ES索引
                sendBookEvent(BookEventDto.createDeleteEvent(id, book.getTitle()));
                log.info("图书删除成功，已发送Kafka消息通知删除ES索引: bookId={}, title={}", id, book.getTitle());
                return ResponseResult.okResult("删除成功");
            } else {
                return ResponseResult.errorResult(500, "删除图书失败");
            }
        } catch (Exception e) {
            log.error("删除图书失败, id={}", id, e);
            return ResponseResult.errorResult(500, "删除图书失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ResponseResult batchDeleteBooks(List<Integer> ids) {
        try {
            if (ids == null || ids.isEmpty()) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "图书ID列表不能为空");
            }

            int count = bookMapper.deleteBatchIds(ids);
            if (count > 0) {
                // 发送Kafka消息：批量删除图书
                for (Integer id : ids) {
                    sendBookEvent(BookEventDto.createDeleteEvent(id, null));
                }
                log.info("批量删除图书成功，已发送Kafka消息通知删除ES索引: bookIds={}", ids);
                return ResponseResult.okResult("批量删除成功，共删除" + count + "条记录");
            } else {
                return ResponseResult.errorResult(500, "批量删除失败");
            }
        } catch (Exception e) {
            log.error("批量删除图书失败, ids={}", ids, e);
            return ResponseResult.errorResult(500, "批量删除图书失败：" + e.getMessage());
        }
    }
    
    /**
     * 转换Book列表为BookAdminVo列表，并填充分类名称
     */
    private List<BookAdminVo> convertToAdminVo(List<Book> bookList) {
        if (bookList == null || bookList.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 收集所有的分类ID
        Set<Integer> categoryIds = bookList.stream()
                .map(Book::getCategoryId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        
        // 批量查询分类信息
        Map<Integer, String> categoryNameMap = new HashMap<>();
        if (!categoryIds.isEmpty()) {
            List<Category> categories = categoryMapper.selectBatchIds(categoryIds);
            categoryNameMap = categories.stream()
                    .collect(Collectors.toMap(Category::getId, Category::getName));
        }
        
        // 转换为VO
        List<BookAdminVo> voList = new ArrayList<>();
        for (Book book : bookList) {
            BookAdminVo vo = new BookAdminVo();
            BeanUtils.copyProperties(book, vo);
            
            // 设置分类名称
            if (book.getCategoryId() != null) {
                String categoryName = categoryNameMap.get(book.getCategoryId());
                vo.setCategoryName(categoryName != null ? categoryName : "未知分类");
            } else {
                vo.setCategoryName("未分类");
            }
            
            voList.add(vo);
        }
        
        return voList;
    }
    
    /**
     * 发送图书事件到Kafka
     */
    private void sendBookEvent(BookEventDto event) {
        if (kafkaTemplate != null) {
            try {
                String message = JSON.toJSONString(event);
                kafkaTemplate.send(KafkaConstants.BookTopics.BOOK_EVENTS, message);
                log.debug("发送图书事件到Kafka: {}", message);
            } catch (Exception e) {
                // Kafka发送失败不影响主流程，只记录日志
                log.error("发送图书事件到Kafka失败: {}", event, e);
            }
        } else {
            log.warn("KafkaTemplate未配置，跳过发送图书事件");
        }
    }
}

